package me.nereo.multi_image_selector.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Bitmap.CompressFormat;
import android.media.ExifInterface;
import android.os.Build;
import android.util.Log;
import android.widget.ImageView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.squareup.picasso.Transformation;

public class ImageHelper {

	private static final String TAG = ImageHelper.class.getSimpleName();

	public static Bitmap resampleImage(final File file, final int maxDim)
			throws Exception {
		return ImageHelper.resampleImage(file.getAbsolutePath(), maxDim);
	}

	public static Bitmap resampleImage(final String path, final int maxDim)
			throws Exception {

		final BitmapFactory.Options bfo = new BitmapFactory.Options();
		bfo.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, bfo);

		final BitmapFactory.Options optsDownSample = new BitmapFactory.Options();
		optsDownSample.inSampleSize = ImageHelper.getClosestResampleSize(
				bfo.outWidth, bfo.outHeight, maxDim);

		final Bitmap bmpt = BitmapFactory.decodeFile(path, optsDownSample);

		final Matrix m = new Matrix();

		if ((bmpt.getWidth() > maxDim) || (bmpt.getHeight() > maxDim)) {
			final BitmapFactory.Options optsScale = ImageHelper.getResampling(
					bmpt.getWidth(), bmpt.getHeight(), maxDim);
			m.postScale((float) optsScale.outWidth / (float) bmpt.getWidth(),
					(float) optsScale.outHeight / (float) bmpt.getHeight());
		}

		final int sdk = Integer.valueOf(Build.VERSION.SDK);
		if (sdk > 4) {
			final int rotation = ImageHelper.getExifOrientation(path);
			if (rotation != 0) {
				m.postRotate(rotation);
			}
		}
		return Bitmap.createBitmap(bmpt, 0, 0, bmpt.getWidth(),
				bmpt.getHeight(), m, true);
	}

	private static int getClosestResampleSize(final int cx, final int cy,
			final int maxDim) {
		final int max = Math.max(cx, cy);

		int resample = 1;
		for (resample = 1; resample < Integer.MAX_VALUE; resample++) {
			if ((resample * maxDim) > max) {
				resample--;
				break;
			}
		}

		if (resample > 0) {
			return resample;
		}
		return 1;
	}

	private static BitmapFactory.Options getResampling(final int cx,
			final int cy, final int max) {
		float scaleVal = 1.0f;
		final BitmapFactory.Options bfo = new BitmapFactory.Options();
		if (cx > cy) {
			scaleVal = (float) max / (float) cx;
		} else if (cy > cx) {
			scaleVal = (float) max / (float) cy;
		} else {
			scaleVal = (float) max / (float) cx;
		}
		bfo.outWidth = (int) ((cx * scaleVal) + 0.5f);
		bfo.outHeight = (int) ((cy * scaleVal) + 0.5f);
		return bfo;
	}

	public static int getExifOrientation(final String filepath) {
		int degree = 0;
		ExifInterface exif = null;
		try {
			exif = new ExifInterface(filepath);
		} catch (final IOException ex) {
			Log.e(ImageHelper.TAG, "cannot read exif", ex);
		}
		if (exif != null) {
			final int orientation = exif.getAttributeInt(
					ExifInterface.TAG_ORIENTATION, -1);
			if (orientation != -1) {
				// We only recognize a subset of orientation tag values.
				switch (orientation) {
				case ExifInterface.ORIENTATION_ROTATE_90:
					degree = 90;
					break;
				case ExifInterface.ORIENTATION_ROTATE_180:
					degree = 180;
					break;
				case ExifInterface.ORIENTATION_ROTATE_270:
					degree = 270;
					break;
				}

			}
		}
		return degree;
	}

	private static int sThumbWidth = 80;
	private static int sThumbHeight = 80;

	public static Bitmap getBitmap(File f) {
		int maxSize = 800;
		return getBitmap(f, maxSize, maxSize);
	}

	/**
	 * ��ȡָ����ߵ�ͼƬ����߹����ο�������̫�󴥷�oom�����ᾫȷ���˳ߴ磬�ᱣ��ͼƬԭ�гߴ�����
	 * 
	 * @param w
	 *            �ο���
	 * @param h
	 *            �ο��߶�
	 * @param f
	 *            ͼƬ�ļ�
	 * */
	public static Bitmap getBitmap(File f, int w, int h) {
		BitmapFactory.Options opts = new BitmapFactory.Options();

		opts.inJustDecodeBounds = true;
		opts.inPurgeable = true;
		opts.inInputShareable = true;
		opts.inPreferredConfig = Bitmap.Config.RGB_565;// jpgͼƬû��͸��ͨ��
		BitmapFactory.decodeFile(f.getAbsolutePath(), opts);
		if (w < opts.outWidth || h < opts.outHeight) {
			opts.inSampleSize = Math.min(opts.outWidth / w, opts.outHeight / h);
		}
		opts.inJustDecodeBounds = false;

		return BitmapFactory.decodeFile(f.getAbsolutePath(), opts);
	}

	/**
	 * @see public static Bitmap getThumb(File f, int w, int h, boolean exactly)
	 * 
	 *      ���80
	 * */
	public static Bitmap getThumb(File f, boolean exactly) {
		return getThumb(f, sThumbWidth, sThumbHeight, exactly);
	}

	/**
	 * ��ȡָ����ߵ�����ͼ����߹����ο�������̫�󴥷�oom�����ᾫȷ���˳ߴ磬�ᱣ��ͼƬԭ�гߴ�����
	 * 
	 * @param w
	 *            �ο���
	 * @param h
	 *            �ο��߶�
	 * @param f
	 *            ͼƬ�ļ�
	 * @param exactly
	 *            Ϊtrueʱ���ᱣ��һ���봫��Ŀ����ȣ�����ԭͼ�����
	 * */
	public static Bitmap getThumb(File f, int w, int h, boolean exactly) {
		Bitmap bmp = getBitmap(f, w, h);

		if (exactly && (bmp.getWidth() != w || bmp.getHeight() != h)) {
			float scaleX = ((float) bmp.getWidth()) / w;
			float scaleY = ((float) bmp.getHeight()) / h;
			float scale = Math.max(scaleX, scaleY);

			Matrix m = new Matrix();
			m.setScale(scale, scale);

			bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
					bmp.getHeight(), m, true);
			// int x = 0;
			// int y = 0;
			// x = Math.max(0, (int) (bmp.getWidth()*scale - w) / 2);
			// y = Math.max(0, (int) (bmp.getHeight()*scale - h) / 2);
			//
			// int width = bmp.getWidth();
			// if(x > 0 && scale < 1f){
			// width = (int) (bmp.getWidth()*scale);
			// }
			// int height = bmp.getHeight();
			// if(y > 0 && scale < 1f){
			// height = (int) (bmp.getHeight()*scale);
			// }
			//
			// bmp = Bitmap.createBitmap(bmp, x, y, width, height, m, true);
		}

		return bmp;
	}

	/**
	 * ��bitmap���浽ָ���ļ��� ����ļ��Ѵ��ڻᱻ����
	 * */
	public static void saveBitmapToFile(Bitmap bmp, File f) {
		saveBitmapToFile(bmp, f, 80);
	}

	/**
	 * ��bitmap���浽ָ���ļ��� ����ļ��Ѵ��ڻᱻ����
	 * 
	 * @param quality
	 *            ѹ������
	 * */
	public static void saveBitmapToFile(Bitmap bmp, File f, int quality) {
		if (!f.exists()) {
			if (!f.getParentFile().exists()) {
				f.getParentFile().mkdirs();
			}
			try {
				f.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(f);
			bmp.compress(CompressFormat.JPEG, quality, fos);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (fos != null) {
					fos.flush();
					fos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * ���ر���ͼƬ
	 * 
	 * @param url
	 * @return
	 */
	public static Bitmap getLoacalBitmap(String path) {
		try {
			FileInputStream fis = new FileInputStream(path);
			BitmapFactory.Options options = new BitmapFactory.Options();
			BitmapFactory.decodeFile(path, options);
			options.inPreferredConfig = Bitmap.Config.RGB_565;
			options.inPurgeable = true;
			options.inInputShareable = true;
			options.inSampleSize = 1;
			return BitmapFactory.decodeStream(fis, null, options);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * ���ر���ͼƬ
	 * 
	 * @param url
	 * @return
	 */
	public static Bitmap getLoacalBitmap(String path, int sampleSize) {
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inPreferredConfig = Bitmap.Config.RGB_565;
		options.inPurgeable = true;
		options.inInputShareable = true;
		options.inSampleSize = sampleSize;
		return BitmapFactory.decodeFile(path, options);
	}
	
	  public static Transformation getTransformation(final ImageView view,final int targetWidth) {
	        return new Transformation() {
	            @Override
	            public Bitmap transform(Bitmap source) {

	                //返回原图
	                if (source.getWidth() == 0 || source.getWidth() < targetWidth) {
	                    return source;
	                }

	                //如果图片大小大于等于设置的宽度，则按照设置的宽度比例来缩放
	                double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
	                int targetHeight = (int) (targetWidth * aspectRatio);
	                if (targetHeight == 0 || targetWidth == 0) {
	                    return source;
	                }
	                Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
	                if (result != source) {
	                    // Same bitmap is returned if sizes are the same
	                    source.recycle();
	                }
	                return result;
	            }

	            @Override
	            public String key() {
	                return "transformation" + " desiredWidth";
	            }
	        };
	    }

}
